/**
 * Copyright (C) 2016 Robinhood Markets, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.jinatonic.confetti.confetto;

import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.ColorFilter;
import ohos.agp.render.Paint;
import ohos.agp.utils.Matrix;
import ohos.media.image.PixelMap;
import ohos.miscservices.timeutility.Time;

import java.util.Random;

public class ShimmeringConfetto extends BitmapConfetto {
    private final int fromColor;
    private final int toColor;

    private final long waveLength;
    private final long halfWaveLength;

    private final long randomStart;

    public ShimmeringConfetto(PixelMap bitmap, int fromColor, int toColor, long waveLength, Random random) {
        super(bitmap);
        this.fromColor = fromColor;
        this.toColor = toColor;
        this.waveLength = waveLength;
        this.halfWaveLength = waveLength / 2;

        final int currentTime = Math.abs((int) Time.getRealTime());
        this.randomStart = currentTime - random.nextInt(currentTime);
    }

    @Override
    protected void drawInternal(
            Canvas canvas, Matrix matrix, Paint paint, float x, float y, float rotation, float percentageAnimated) {
        final long currTime = Time.getRealTime();
        final long fraction = (currTime - randomStart) % waveLength;
        final float animated =
                fraction < halfWaveLength
                        ? (float) fraction / halfWaveLength
                        : ((float) waveLength - fraction) / halfWaveLength;

        final int color = (int) evaluate(animated, fromColor, toColor);
        final ColorFilter colorFilter = new ColorFilter(color, BlendMode.SRC_ATOP);
        paint.setColorFilter(colorFilter);
        super.drawInternal(canvas, matrix, paint, x, y, rotation, percentageAnimated);
    }

    private Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        float startA = ((startInt >> 24) & 0xff) / 255.0f;
        float startR = ((startInt >> 16) & 0xff) / 255.0f;
        float startG = ((startInt >> 8) & 0xff) / 255.0f;
        float startB = (startInt & 0xff) / 255.0f;

        int endInt = (Integer) endValue;
        float endA = ((endInt >> 24) & 0xff) / 255.0f;
        float endR = ((endInt >> 16) & 0xff) / 255.0f;
        float endG = ((endInt >> 8) & 0xff) / 255.0f;
        float endB = (endInt & 0xff) / 255.0f;

        // convert from sRGB to linear
        startR = (float) Math.pow(startR, 2.2);
        startG = (float) Math.pow(startG, 2.2);
        startB = (float) Math.pow(startB, 2.2);

        endR = (float) Math.pow(endR, 2.2);
        endG = (float) Math.pow(endG, 2.2);
        endB = (float) Math.pow(endB, 2.2);

        // compute the interpolated color in linear space
        float a = startA + fraction * (endA - startA);
        float r = startR + fraction * (endR - startR);
        float g = startG + fraction * (endG - startG);
        float b = startB + fraction * (endB - startB);

        // convert back to sRGB in the [0..255] range
        a = a * 255.0f;
        r = (float) Math.pow(r, 1.0 / 2.2) * 255.0f;
        g = (float) Math.pow(g, 1.0 / 2.2) * 255.0f;
        b = (float) Math.pow(b, 1.0 / 2.2) * 255.0f;

        return Math.round(a) << 24 | Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b);
    }
}
